home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / pas / swag / crc.swg / 0008_File MODS With CRC Check.pas < prev    next >
Pascal/Delphi Source File  |  1993-05-28  |  8KB  |  223 lines

  1. {$X+}
  2. Unit selfmod;
  3.  
  4.  { Author Trevor J Carlsen - released into the public domain 1991            }
  5.  {        PO Box 568                                                         }
  6.  {        Port Hedland                                                       } 
  7.  {        Western Australia 6721                                             }
  8.  {        Voice +61 91 73 2026  Data +61 91 73  2569                         }
  9.  {        FidoNet 3:690/644                                                  }
  10.  { Allows a Program to self modify a Typed Constant in the .exe File.  It    }
  11.  { also perForms an automatic checksum Type .exe File integrity check.       }
  12.  { A LongInt value is added to the end of the exe File.  This can be read by }
  13.  { a separate configuration Program to enable it to determine the start of   }
  14.  { the Programs configuration data area.  to use this the configuration      }
  15.  { Typed Constant should be added immediately following the declaration of   }
  16.  { ExeData.                                                                  }
  17.  
  18.  { Where this Unit is used, it should always be the FIRST Unit listed in the }
  19.  { Uses declaration area of the main Program.                                }
  20.  
  21.  { Requires Dos 3.3 or later.  Program must not be used With PKLite or LZExe }
  22.  { or any similar exe File Compression Programs. It may also cause           }
  23.  { difficulties on a network or virus detection Programs.                    }
  24.  
  25.  { The stack size needed is at least 9,000 Bytes.                            }
  26.  
  27. Interface
  28.  
  29. Uses
  30.   globals;
  31.  
  32. Type
  33.   ExeDataType    = Record
  34.                      IDStr      : str7;
  35.                      UserName   : str35;
  36.                      FirstTime  : Boolean;
  37.                      NumbExecs  : shortint;
  38.                      Hsize      : Word;
  39.                      ExeSize    : LongInt;
  40.                      CheckSum   : LongInt;
  41.                      StartConst : LongInt;
  42.                      RegCode    : LongInt;
  43.                    end;
  44. Const
  45.   ExeData : ExeDataType = (IDStr     : 'ID-AREA';
  46.                            UserName  : '';
  47.                            FirstTime : True;
  48.                            NumbExecs : -1;
  49.                            Hsize     : 0;
  50.                            ExeSize   : 0;
  51.                            CheckSum  : 0;
  52.                            StartConst: 0;
  53.                            RegCode   : 0);
  54.  
  55.  
  56. {$I p:\prog\freeload.inc} { Creates CodeStr that MUST match RegStr }
  57.  
  58. {$I p:\prog\registed.inc} { Creates CodeChkStr that MUST hash to RegCode}
  59.  
  60. Const
  61.   mark  : Byte = 0;
  62.  
  63. Var
  64.   first : Boolean;
  65.  
  66. Procedure Hash(p : Pointer; numb : Byte; Var result: LongInt);
  67.  
  68. Function Write2Exec(Var data; size: Word): Boolean;
  69.  
  70. Implementation
  71.  
  72.  
  73. Procedure Hash(p : Pointer; numb : Byte; Var result: LongInt);
  74.   { When originally called numb must be equal to sizeof    }
  75.   { whatever p is pointing at.  if that is a String numb   }
  76.   { should be equal to length(the_String) and p should be  }        
  77.   { ptr(seg(the_String),ofs(the_String)+1)                 }
  78.   Var
  79.     temp,
  80.     w    : LongInt;
  81.     x    : Byte;
  82.  
  83.   begin
  84.     temp := LongInt(p^);  RandSeed := temp;
  85.     For x := 0 to (numb - 4) do begin
  86.       w := random(maxint) * random(maxint) * random(maxint);
  87.       temp := ((temp shr random(16)) shl random(16)) +
  88.                 w + MemL[seg(p^):ofs(p^)+x];
  89.     end;
  90.     result := result xor temp;
  91.   end;  { Hash }
  92.  
  93.  
  94. Procedure InitConstants;
  95.   Var
  96.     f           : File;
  97.     tbuff       : Array[0..1] of Word;
  98.   
  99.   Function GetCheckSum : LongInt;  
  100.     { PerForms a checksum calculation on the exe File }
  101.     Var
  102.       finished  : Boolean;
  103.       x,
  104.       CSum      : LongInt;
  105.       BytesRead : Word;
  106.       buffer    : Array[0..4095] of Word;
  107.     begin
  108.       {$I-}
  109.       seek(f,0);
  110.       finished := False;  CSum := 0;  x := 0;
  111.       BlockRead(f,buffer,sizeof(buffer),BytesRead);
  112.       While not finished do begin             { do the checksum calculations }
  113.         Repeat         { Until File has been read up to start of config area }
  114.           inc(CSum,buffer[x mod 4096]);
  115.           inc(x);
  116.           finished := ((x shl 1) >= ExeData.StartConst); 
  117.         Until ((x mod 4096) = 0) or finished;
  118.         if not finished then                { data area has not been reached }
  119.           BlockRead(f,buffer,sizeof(buffer),BytesRead);          
  120.       end;
  121.       GetCheckSum := CSum;
  122.     end; { GetCheckSum }
  123.     
  124.       
  125.   begin
  126.     assign(f, ParamStr(0));
  127.     {$I-} Reset(f,1);
  128.     With ExeData do begin
  129.       first := FirstTime;
  130.       if FirstTime and (Ioresult = 0) then begin
  131.         Seek(f,2);                   { this location has the executable size }
  132.         BlockRead(f,tbuff,4);
  133.         ExeSize := tbuff[0]+(pred(tbuff[1]) shl 9);
  134.         seek(f,8);                                    {  get the header size }
  135.         BlockRead(f,hsize,2);
  136.         FirstTime := False;
  137.         StartConst := LongInt(hsize+Seg(ExeData)-PrefixSeg) shl 4 + 
  138.                       ofs(ExeData) - 256;
  139.         CheckSum := GetCheckSum;
  140.         Seek(f,StartConst);
  141.         BlockWrite(f,ExeData,sizeof(ExeData));
  142.         seek(f,FileSize(f));
  143.         BlockWrite(f,StartConst,4);
  144.       end
  145.       else
  146.         if GetCheckSum <> CheckSum then begin
  147.           Writeln('File has been tampered with.  Checksum incorrect');
  148.           halt;
  149.         end;
  150.     end;  { With }    
  151.     Close(f); {$I+}
  152.     if Ioresult <> 0 then begin
  153.       Writeln('Unable to initialise Program');
  154.       halt;
  155.     end;  
  156.   end; { InitConstants }
  157.  
  158.  
  159. Function Write2Exec(Var data; size: Word): Boolean;
  160.  { Writes a new Typed Constant into the executable File after first checking }
  161.  { that it is safe to do so.  It does this by ensuring that the IDString is  }
  162.  { at the File offset expected.                                              }
  163.   Const
  164.     FName : str40 = '';
  165.   Var
  166.      f          : File;
  167.      st         : str8;
  168.      BytesRead  : Word;
  169.   begin
  170.     if UseCfg then begin
  171.       if length(FName) = 0 then begin
  172.         TempStr    := ParamStr(0);
  173.         TempStrLen := pos('.',TempStr) - 2;
  174.         FName      := TempStr + ' .   ';
  175.         {                        │ │││                                       }
  176.         {                        │ ││└────»» #255                            }
  177.         {                        │ │└─────»» #32                             }
  178.         {                        │ └──────»» #255                            }
  179.         {                        └────────»» #255                            }
  180.         { Using the above File name For the configuration File makes the     }
  181.         { deletion of the File difficult For the average user.               }
  182.       end; { if length }
  183.       assign(f, FName);
  184.       if exist(FName) then begin
  185.         {$I-}
  186.         reset(f,1);
  187.         if first then begin
  188.           first := False;
  189.           BlockRead(f, ExeData, ofs(mark)-ofs(ExeData),BytesRead)
  190.         end else
  191.           BlockWrite(f,data,size);
  192.       end else begin
  193.         reWrite(f,1);
  194.         BlockWrite(f,Data,size);
  195.       end;
  196.       close(f);
  197.       {$I+}
  198.       Write2Exec := Ioresult = 0;
  199.     end else begin
  200.       assign(f, ParamStr(0));
  201.       {$I-} Reset(f,1);
  202.       Seek(f,LongInt(ExeData.Hsize+Seg(ExeData)-PrefixSeg) shl 4
  203.                      + ofs(ExeData)- 256);
  204.       BlockRead(f,st,9);
  205.       if st = ExeData.IDStr then { all Ok to proceed } begin
  206.         Seek(f,LongInt(ExeData.Hsize+Seg(data)-PrefixSeg) shl 4
  207.                        + ofs(data)- 256);
  208.         BlockWrite(f,data,size);
  209.         Close(f); {$I+}
  210.         Write2Exec := Ioresult = 0;
  211.       end else
  212.         Write2Exec := False;
  213.     end;
  214.   end; { Write2Exec }
  215.   
  216. begin
  217.   first :=  True;
  218.   if not UseCfg then
  219.     InitConstants
  220.   else
  221.     Write2Exec(ExeData,ofs(mark)-ofs(ExeData));
  222. end.
  223.